package com.zip;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.lang.StringUtils;

import java.io.File;

/**
 * @author ZhangYue26
 * @date 2020-07-07 15:57
 * @Description: 文件解压缩示例  zip压缩包
 */
public class CompressDemo {

    public static void main(String[] args) {
//        压缩
//        compressedFile("C:\\Users\\zhangyue26\\Desktop\\test.txt");
        //解压
        unZipFile("C:\\Users\\zhangyue26\\Desktop\\test.zip");
    }


    public static final String COMPRESS_TYPE = ".zip";
/**===========================压缩==================================**/
    /**
     * @Author ZhangYue26
     * @Description: 压缩指定文件
     * @Description //TODO
     * @Date 2020/7/7 16:30
     * @Param [filePath]
     * @return java.lang.String
     **/
    public static String compressedFile(String filePath) {
        return compressedFileAndPassword(filePath, null);
    }

    /**
     * @Author ZhangYue26
     * @Description: 压缩指定文件并指定密码
     * @Description //TODO
     * @Date 2020/7/7 16:13
     * @Param [filePath, password]
     * @return java.lang.String
     **/
    private static String compressedFileAndPassword(String filePath, String password) {
        return compressedFileAndPasswordAndTargetDirectory(filePath, null, password);
    }
    
    /**
     * @Author ZhangYue26
     * @Description: 压缩指定文件并指定文件目标目录与密码
     * @Description //TODO 
     * @Date 2020/7/7 16:26 
     * @Param [filePath, targetDirectory, password]
     * @return java.lang.String
     **/
    private static String compressedFileAndPasswordAndTargetDirectory(String filePath, String targetFileName, String password) {
        return compress(filePath, targetFileName, true, password);
    }
    
    /**
     * @Author ZhangYue26
     * @Description: 压缩指定文件并指定文件目标目录与密码，   isCreateDir 是否在压缩文件里创建目录，仅在压缩文件为目录时有效。若为false，则直接压缩目录下文件到压缩文件
     * @Description //TODO 
     * @Date 2020/7/7 16:27 
     * @Param [filePath, targetFileName, isCreateDir, password]
     * @return java.lang.String
     **/
    private static String compress(String filePath, String targetFileName, boolean isCreateDir, String password) {
        File srcFile = new File(filePath);
        targetFileName = createDestinationPath(srcFile, targetFileName);
        ZipParameters parameters = new ZipParameters();
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        if (password != null && !"".equals(password)) {
            parameters.setEncryptFiles(true);
            parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
            parameters.setPassword(password.toCharArray());
        }
        try {
            ZipFile zipFile = new ZipFile(targetFileName);
            if (srcFile.isDirectory()) {
                //如果不创建目录，将直接把给定目录下的文件压缩到文件夹，即没有目录结构
                if (!isCreateDir) {
                    File[] subFiles = srcFile.listFiles();
                    int num = 0;
                    if (subFiles != null) {
                        num = subFiles.length;
                        for (int i = 0; i < num; i++) {
                            if (subFiles[i].isDirectory()) {
                                compress(subFiles[i].getAbsolutePath(), targetFileName, isCreateDir, password);
                            } else {
                                zipFile.addFile(subFiles[i], parameters);
                            }
                        }
                        return targetFileName;
                    }
                    zipFile.addFolder(srcFile, parameters);
                }
            } else {
                zipFile.addFile(srcFile, parameters);
            }
            return targetFileName;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Author ZhangYue26
     * @Description: 创建指定文件，并返回文件名
     * @Description //TODO
     * @Date 2020/7/7 16:31
     * @Param [srcFile, dest]
     * @return java.lang.String
     **/
    private static String createDestinationPath(File srcFile, String targetFileName) {
        if (targetFileName == null || "".equals(targetFileName)) {
            if (srcFile.isDirectory()) {
                targetFileName = srcFile.getParent() + File.separator + srcFile.getName() + COMPRESS_TYPE;
            } else {
                String fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
                targetFileName = srcFile.getParent() + File.separator + fileName + COMPRESS_TYPE;

            }
        } else {
            createDestinationPath(targetFileName);
            if (targetFileName.endsWith(File.separator)) {
                String fileName = "";
                if (srcFile.isDirectory()) {
                    fileName = srcFile.getName();
                } else {
                    fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
                }
                targetFileName += fileName + COMPRESS_TYPE;
            }

        }
        return targetFileName;
    }

    /**
     * @Author ZhangYue26
     * @Description: 创建指定文件夹及文件
     * @Description //TODO
     * @Date 2020/7/7 16:32
     * @Param [targetFileName]
     * @return boolean
     **/
    private static boolean createDestinationPath(String targetFileName) {
        File destDir = null;
        if (targetFileName.endsWith(File.separator)) {
            destDir = new File(targetFileName);
        } else {
            destDir = new File(targetFileName.substring(0, targetFileName.lastIndexOf(File.separator)));
        }
        if (!destDir.exists()) {
            return destDir.mkdirs();
        }
        return false;
    }



    /**=======================解压===========================**/
    
    /**
     * @Author ZhangYue26
     * @Description: 解压指定的文件
     * @Description //TODO 
     * @Date 2020/7/7 16:24 
     * @Param [unZipBeforeFile]
     * @return void
     **/
    public static void unZipFile(String unZipBeforeFile) {
        File src = new File(unZipBeforeFile);
        String destName = src.getParent() + File.separator;
        unZipFileByTargetDirectory(unZipBeforeFile, destName);
    }
    
    /**
     * @Author ZhangYue26
     * @Description: 解压指定文件并指定文件夹
     * @Description //TODO 
     * @Date 2020/7/7 16:24 
     * @Param [unZipBeforeFile, destName]
     * @return void
     **/
    private static void unZipFileByTargetDirectory(String unZipBeforeFile, String destName) {
        unZipFileByTargetDirectoryAndPassword(unZipBeforeFile, destName, null);
    }
    
    /**
     * @Author ZhangYue26
     * @Description: 解压指定文件并指定目标文件夹以及密码
     * @Description //TODO 
     * @Date 2020/7/7 16:25 
     * @Param [unZipBeforeFile, destName, password]
     * @return void
     **/
    private static void unZipFileByTargetDirectoryAndPassword(String unZipBeforeFile, String destName, String password) {
        try {
            File file = new File(unZipBeforeFile);
            ZipFile zipFile = new ZipFile(file);
            zipFile.setFileNameCharset("UTF-8");
            if (!zipFile.isValidZipFile()) {
                throw new ZipException("压缩文件不合法，可能损坏");
            }
            File f = new File(destName);
            if (f.isDirectory() && !f.exists()) {
                f.mkdir();
            }
            if (zipFile.isEncrypted() && StringUtils.isBlank(password)) {
                zipFile.setPassword(password.toCharArray());
            }
            zipFile.extractAll(destName);
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }


}
